// @ts-nocheck
/**
 * 数组扁平化
 * @param {*} arr 数组
 * @returns
 */
function flatten(arr = []) {
	return arr.reduce((pre, cur) => {
		return pre.concat(Array.isArray(cur) ? flatten(cur) : cur)
	}, [])
}
const arr = [1, 23, [1, [1, [2]]]]

function flatter2(arr = []) {
	let res = []
	function _(arr) {
		arr.forEach((item) => {
			if (Array.isArray(item)) {
				_(item)
			} else {
				res.push(item)
			}
		})
	}
	_(arr)
	return res
}
let res = JSON.parse(
	'[' + JSON.stringify(arr).replace(/\[|\]/g, '').split(',') + ']'
)
// console.log(flatten(arr))
// console.log(arr.flat(Infinity))
// console.log(flatter2(arr))
// console.log(res)

/**
 * 数组去重
 * @param {*} arr
 * @returns
 */

// function unique(arr = []) {
// 	let map = {}
// 	return arr.filter((item) =>
// 		map.hasOwnProperty(typeof item + item)
// 			? false
// 			: (map[typeof item + item] = true)
// 	)
// }
// var arrTest2 = [
// 	1,
// 	1,
// 	'true',
// 	'true',
// 	true,
// 	true,
// 	15,
// 	15,
// 	false,
// 	false,
// 	undefined,
// 	undefined,
// 	null,
// 	null,
// 	NaN,
// 	NaN,
// 	'NaN',
// 	0,
// 	0,
// 	'a',
// 	'a',
// 	{},
// 	{},
// ]
// console.log(unique(arrTest2))

/**
 * call
 * 改变this 接收逗号分割的参数
 * 实现：在函数内部使用 参数传来的this 调用参数传来的函数
 */

function call(context = window, ...args) {
	if (typeof this !== 'function') {
		throw new TypeError(' fn must to be a function ')
	}

	const fn = Symbol('fn')
	context[fn] = this

	const res = context[fn](...args)
	delete context[fn]
	return res
}
const test = [1, 2, 3]

Function.prototype.call = call
Function.prototype.apply = apply
// Function.prototype.bind = bind

function display(arr) {
	console.log(this)
	console.log(arr)
}

// display.call(test, 111111, 1, 15, 4, 54)

/**
 * apply
 * 改变this的指向 接收数组形式的参数
 * 实现：在函数内部使用 参数传来的this 调用参数传来的函数
 */
function apply(context = window, arr) {
	if (typeof this !== 'function') {
		throw new TypeError(' fn must to be a function ')
	}
	const fn = Symbol('fn')
	context[fn] = this

	const res = context[fn](...arr)
	delete context[fn]
	return res
}

// display.apply(test, [1, 15, 4, 54])

/***
 * bind
 * 改变this的指向  返回一个新的函数
 * 实现：在函数内部使用 参数传来的this 调用参数传来的函数 并返回一个新函数
 *
 */
// function bind(context = window, ...arr) {
// 	if (typeof this !== 'function') {
// 		throw new TypeError(' fn must to be a function ')
// 	}
// 	const fn = Symbol('fn')
// 	context[fn] = this
// 	return function (...args) {
// 		const result = context[fn](...[...arr, ...args])
// 		delete context[fn]
// 		return result
// 	}
// }

// const f = display.bind(test, [1, 1, 1, 1, 1])(45)

/**
 * 防抖 踢皮球
 * 函数等一段时间在执行
 *
 */
function debounce(fn, wait) {
	let timer = null
	return function (...args) {
		timer && clearInterval(timer)
		timer = queueMicrotask(() => {
			fn.apply(this, args)
			timer = null
		}, wait)
	}
}

/**
 * 节流 打孔机
 * 每隔一个固定时间就执行一次
 */

function throttle(fn, interval) {
	let startTime = 0
	return function (...args) {
		let nowTime = Date.now()
		if (interval - (nowTime - startTime) <= 0) {
			fn.apply(this, args)
			startTime = nowTime
		}
	}
}

/**
 * 柯里化
 * 递归 收集参数，并将收集的参数作为新函数的参数向下传递
 * 直到参数个数达到函数要求的个数 再调用被柯里化的函数
 *  fn(10)(20)(30,40)
 */

function sun(x, y, z) {
	return x + y + z
}

function Curry(fn) {
	return function _curry(...args) {
		if (args.length >= fn.length) {
			return fn.apply(this, args)
		} else {
			return function (...arr) {
				return _curry.apply(this, [...arr, ...args])
			}
		}
	}
}
const ff = Curry(sun)
// console.log(ff(1)(1, 1))

/**
 * 纯函数
 */

/**
 * js 继承
 */

// Object.create =  function(o){
// 	const F = function(){}
// 	f.prototype = o
// 	return new F()
// }

function inheritPrototype(Person, Son) {
	const prototype = Object.create(Person)
	prototype.construct = Son
	Son.prototype = prototype
}
function Person(arg) {}
Person.prototype.say = function () {
	console.log(1)
}
function Son(...arg) {
	Person.call(this, arg)
}
// 先继承之后在 添加自己的方法
inheritPrototype(Person, Son)

Son.prototype.say1 = function () {
	console.log(2)
}

const s1 = new Son()
// s1.say1()

/**
 * 常见的算法题
 */

// 每隔 time 秒 输出 1 2 3 .... (作用域 / 闭包 / 自执行函数)
function fn(time) {
	for (let i = 0; i < 10; i++) {
		queueMicrotask(() => {
			console.log(i)
		}, time * i)
	}
}

function fn2(time) {
	for (var i = 0; i < 10; i++) {
		;(function (i) {
			queueMicrotask(() => {
				console.log(i)
			}, time * i)
		})(i)
	}
}
// fn(1000)

// 输出红绿灯问题 ：Promise 隔三秒打印red，再隔2秒打印green，再隔1秒打印yellow，依次循环无限打印
// function red() {
// 	console.log('red')
// }

// function green() {
// 	console.log('green')
// }

// function yellow() {
// 	console.log('yellow')
// }

// function pro(time, fn) {
// 	return new Promise((resolve, reject) => {
// 		queueMicrotask(() => {
// 			fn()
// 			resolve()
// 		}, time)
// 	})
// }

// function settimefn() {
// 	pro(3000, red)
// 		.then(() => {
// 			return pro(2000, green)
// 		})
// 		.then(() => {
// 			return pro(1000, yellow)
// 		})
// 		.finally(() => {
// 			settimefn()
// 		})
// }

// settimefn()

function sleep(duration) {
	return new Promise((resolve) => {
		queueMicrotask(resolve, duration)
	})
}
async function changeColor(color, duration) {
	console.log('traffic-light ', color)
	await sleep(duration)
}
async function main() {
	while (true) {
		await changeColor('red', 2000)
		await changeColor('yellow', 1000)
		await changeColor('green', 3000)
	}
}
// main()

// 统计每一个字符串出现次数 / 最多出现的字符

function strCount(str) {
	const res = Array.from(str).reduce((p, c) => {
		p[c] ? p[c]++ : (p[c] = 1)
		return p
	}, {})
	return res
}
function maxCount(obj) {
	return Object.keys(obj)
		.reduce((p, c) => [...p, [c, obj[c]]], [])
		.sort((a, b) => a[1] - b[1])
		.pop()
}

let str = 'xxdfjfjjfjeoijejgfjgjfgsjajfahgashfhugnasfgdwhoutqtbn'
// strCount(str)
// console.log(maxCount(strCount(str)))

// 如何将浮点数点左边的数每三位添加一个逗号，如 12000000.11 转化为『12,000,000.11』?
function format(number) {
	return number && number.replace(/(?!^)(?=(\d{3})+\.)/g, ',')
}

// “LRU（最近最少使用）”算法
/**
 *添加   存在：先删除后添加，判断长度是否超出容量
	                          超出:删除数组最后一个
	       不存在:直接添加
	删除   存在：直接删除
         不存在 返回 null
	查看   存在 先删除 后添加 返回查找到的元素
         不存在：返回 null
 */

class LRU {
	size
	arr
	constructor(size) {
		this.size = size
		this.arr = []
		this.map = new Map()
	}
	add(el) {
		if (!this.map.has(el)) {
			this.arr.unshift(el)
			this.map.set(el, el)
		} else {
			this.arr = this.arr.filter((item) => item != el)
			this.arr.unshift(el)
		}
		if (this.arr.length > this.size) {
			this.arr.pop()
		}
	}
	del(el) {
		if (!this.map.has(el)) {
			return null
		} else {
			this.arr = this.arr.filter((item) => item != el)
			this.map.delete(el)
		}
	}
	get(el) {
		if (!this.map.has(el)) {
			return null
		} else {
			const item = this.arr.find((item) => item === el)
			this.arr = this.arr.filter((item) => item != el)
			this.arr.unshift(item)
		}
	}
}

const lru = new LRU(3)
lru.add(1)
lru.add(2)
lru.del(2)
lru.add(3)
lru.add(4)
lru.get(2)
lru.add(1)
lru.add(2)
lru.del(2)
lru.add(3)
lru.add(4)
// console.log(lru.arr)

// 判断是否是一个素数
/**
 * 2 3 5 7 11 13 17
 * 1. 从3 开始
 * 2. 不能被2 整除
 * 3. 因子只能有 1 和 自己本身
 *
 * @param {*} n
 */
function isPrime(n) {
	if (n === 2 || n === 3) {
		return true
	}
	if (n % 2 === 0) {
		return false
	}
	const maxI = Math.sqrt(n)
	let i = 3
	let flag = true
	while (i <= maxI) {
		if (n % i == 0) {
			flag = false
		}
		i++
	}
	return flag
}
// console.log(isPrime(4))
// console.log(isPrime(11))
// console.log(isPrime(112))
// console.log(isPrime(2))
// console.log(isPrime(17))

// 斐波那契
/**
 * 1、1、2、3、5、8、13、21、34
 * 规律 后一项 等于 前两项之和
 */

function fibonacci(n) {
	if (n === 1 || n === 2) return 1
	return fibonacci(n - 1) + fibonacci(n - 2)
}

function fibonacci2(n) {
	if (n === 1 || n === 2) return 1
	let f = 1,
		s = 1,
		sum = 0
	for (let i = 3; i <= n; i++) {
		sum = f + s
		s = f
		f = sum
	}
	return sum
}

function fibonacci3(n) {
	let cache = [0, 1, 1]
	function _fib(n) {
		if (cache[n]) return cache[n]
		cache[n] = _fib(n - 1) + _fib(n - 2)
		return cache[n]
	}
	return _fib(n)
}
// console.log(fibonacci3(8))

//求最大公约数
/**
 *  选择最小的数  一次累加 取余
 */
function greatestCommonDivisor(...args) {
	const min = Math.min(...args)
	if (args.length === 1) return min
	let i = 1
	let res = 1
	while (i <= min) {
		let flag = true
		for (const item of args) {
			if (item % i !== 0) flag = false
		}
		if (flag) res = i
		i++
	}
	return res
}
// console.log(greatestCommonDivisor(45, 45))

// 去除重复的字符串
/**
 * 利用 splice  或则 转移到末尾在弹出
 *
 */
function uniqueStr(str) {
	str = Array.from(str)
	for (let i = 0; i < str.length; i++) {
		for (let j = i + 1; j < str.length; j++) {
			if (str[i] == str[j]) {
				// const temp = str[str.length - 1]
				// str[str.length - 1] = str[j]
				// str[j] = temp
				// str.pop()
				// j--
				str.splice(j, 1)
				j--
			}
		}
	}
	return str.join('')
}
// console.log(uniqueStr('xjxxxfsjflsffkkkkfsdfsdfsdfxbbb'))

// 排序已近排序好的连个数组
/**
 * 归并排序
 *  1. 申请足够空间
 *  2. 拿出小段 填充到 新数组中
 *  3. 剩余数组填充完毕
 */
function mergeSortedArr(a, b) {
	let i = 1,
		j = 1,
		aH = a[0],
		bH = b[0],
		res = []
	while (aH || bH) {
		if ((aH && !bH) || aH <= bH) {
			res.push(aH)
			aH = a[i++]
		} else {
			res.push(bH)
			bH = b[j++]
		}
	}
	return res
}

// console.log(mergeSortedArr([1, 2, 3], [2, 3, 6]))

function reverse(str) {
	let res = ''
	for (let i = str.length - 1; i >= 0; i--) {
		res += str[i]
	}
	return res
}

// console.log(reverse('abc'))

function reverseInPlace(str) {
	return str.split(' ').reverse().join(' ').split('').reverse().join('')
}
// console.log(reverseInPlace('I am the good boy'))

// 判断是否是回文
/**
 * aba  abba
 * 1. 寻找中点位置
 * 从两边向中间依次比对
 */
function isPalindrome(str) {
	const m = Math.floor(str.length / 2)
	let flag = true
	for (let i = 0; i < m; i++) {
		if (str[i] !== str[str.length - i - 1]) {
			flag = false
			break
		}
	}
	return flag
}

// 判断数组中是否有两数之和
/**
 * [6,4,3,2,1,7]   9
 */

function towSum(arr, sum) {
	let map = new Map()
	let flag = false
	let res = []
	arr.forEach((item) => {
		if (map.has(sum - item)) {
			res.push([item, sum - item])
			flag = true
		} else {
			map.set(item, item)
		}
	})
	// console.log(res)
	// console.log(map)
	return flag
}
// console.log(towSum([6, 4, 3, 2, 1, 7], 5))

//连字符转成驼峰
/**
 * get-element-by-id 转为 getElementById
 * 1. 一 ‘-’ 分割
 * 2. 数组每一项第一项的第一个字符大写
 * 3. join
 */

function hump(str) {
	return str
		.split('-')
		.map((item) => {
			item = item.slice(0, 1).toUpperCase() + item.slice(1)
			return item
		})
		.join('')
}
// console.log(hump('get-element-by-id'))

// .最长公共前缀

/**
 *  ["flower","flow","flight"]
 * "fl"
 *  1. 假设第一个字符是最长公共前缀
 *  2. 与剩下的字符比对 依次缩减字符
 */
function longestCommonPrefix(arr) {
	let maxPrefix = arr[0]
	for (let i = 1; i < arr.length; i++) {
		for (let j = 0; j < arr[i].length; j++) {
			let k = 0
			while (k < arr[i].length) {
				if (maxPrefix[k] !== arr[i][k]) {
					maxPrefix = maxPrefix.slice(0, k)
					if (k === 0) maxPrefix = ''
				}
				k++
			}
		}
	}
	return maxPrefix
}

function longestCommonPrefix2(arr) {
	let maxPrefix = arr[0]
	for (let i = 1; i < arr.length; i++) {
		if (!maxPrefix.length) {
			break
		}
		while (!arr[i].startsWith(maxPrefix)) {
			if (maxPrefix.length === 0) {
				maxPrefix = ''
				break
			} else {
				maxPrefix = maxPrefix.slice(0, maxPrefix.length - 1)
			}
		}
	}
	return maxPrefix
}
// console.log(longestCommonPrefix2(['xflower', 'flow', 'flight']))

// 将数字12345678转化成RMB形式：12,345,678
/**
 *从右边向左变量 缝 3 加逗号
 */

function FormatNum(num) {
	num = num.split('').reverse()
	let res = []
	for (let i = 0; i < num.length; i++) {
		res.push(num[i])
		if ((i + 1) % 3 === 0) {
			res.push(',')
		}
	}
	return res.reverse().join('')
}

// console.log(FormatNum('1234'))

// var name = 'x'
// var people = {
// 	name: 'y',
// 	setName: () => {
// 		this.name = name
// 		return () => {
// 			this.name
// 		}
// 	},
// }
// var getName = people.setName()
// console.log(people.name)
// console.log(getName())

// async function fun() {
// 	console.log(3)
// 	let a = await 4
// 	console.log(a)
// 	console.log(5)
// }
// console.log(1)
// fun()
// console.log(2)

/**
 *  http://api.tianapi.com/lishi/index?key=14406b79def5a61e7501cbd255f3a296&date=0101
 * 1. 创建 XMLHttpRequest 对象
 * 2. 指定回调函数
 * 3. 设置请求 类型 和 url .....
 * 4. 发送请求
 * 5. 处理返回的结果
 */
class MyRequest {
	request(method, url, data) {
		return new Promise((resolve, reject) => {
			const xhr = new XMLHttpRequest()
			xhr.onreadystatechange = function () {
				if (xhr.readyState === 4) {
					if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
						resolve(xhr.responseText)
					} else {
						reject(xhr, xhr.responseText)
					}
				}
			}
			xhr.open(method, url)
			xhr.send(data)
		})
	}
	get() {
		return this.request(
			'get',
			'http://api.tianapi.com/lishi/index?key=14406b79def5a61e7501cbd255f3a296&date=0101'
		)
	}
	post() {
		return this.request('post', 'xxx')
	}
}

// const XHR = new MyRequest()
// XHR.get().then((res) => console.log(res))

// url 参数的解析

let postData = {
	name: 'curr',
	age: 18,
}
function formatParams(params, method) {
	let res = ''
	if (params && typeof params === 'object') {
		let arr = []
		for (const key in params) {
			if (Object.hasOwnProperty.call(params, key)) {
				arr.push(key + '=' + params[key])
			}
		}
		res = arr.join('&')
	}
	return res
}
// console.log(formatParams(postData))
function PaseParams(str) {
	str[0] == '?' ? (str = str.slice(1)) : str
	let res = {}
	str.split('&').forEach((item) => {
		const key = item.split('=')[0]
		const val = item.split('=')[1]
		res[key] = val
	})
	return res
}
// console.log(PaseParams('?userName=zhangsan&age=18'))

function* bar() {
	console.log('step 1')
	yield 1
	console.log('step 2')
	yield 2
	console.log('step 3')
	yield 3
}

let gen = bar()
// console.log(gen.next().value)
// console.log(gen.next().value)
// console.log(gen.next().value)
/**
 *  async  await 的简单实现
 * @param {*} gen
 * @returns
 */

function runGenerator(gen) {
	//把返回值包装成promise
	return new Promise((resolve, reject) => {
		var g = gen()

		function _next(val) {
			//错误处理
			let res = g
			try {
				res = g.next(val)
			} catch (err) {
				return reject(err)
			}

			if (res.done) {
				return resolve(res.value)
			}
			//res.value包装为promise，以兼容yield后面跟基本类型的情况
			Promise.resolve(res.value).then(
				(val) => {
					_next(val)
				},
				(err) => {
					//抛出错误
					g.throw(err)
				}
			)
		}
		_next()
	})
}

function* getData() {
	let path1 = yield 1
	let name = yield 2
	return name
}
runGenerator(getData).then((data) => {
	// console.log(data) //圩上——TAO
})

/**
 * 一个封装的延迟函数，然后一个装有3,4,5的数组，需求就是在开始执行时依次等待3, 4, 5秒，并在之后打印对应输出
 * 延迟函数的本质上就是
 * 	promise + 定时器 ： 在上一次的then 回调函数 调用下一次函数
 *  闭包 + 定时器 ： 创建多个 定时器 在内存中到时间就执向
 */
let delayArr = [1, 3, 5]

function delay(time) {
	return new Promise((resolve, reject) => {
		setTimeout(() => {
			console.log(`wait ${time}s`)
			resolve()
		}, time * 1000)
	})
}
// delay(1)
// 	.then((res) => console.log(res))
// 	.then(() => delay(2).then((res) => console.log(res)))
// 	.then(() => delay(3).then((res) => console.log(res)))

// 函数预编译问题

// function tests(a) {
// 	console.log(a)
// 	var a = 123
// 	console.log(a)
// 	function a() {}
// 	console.log(a)
// 	var b = function () {}
// 	console.log(b)
// 	function d() {}
// }
// tests(1)

/**
 * [
 *
 * {
 * 	type:0, values:[ { name:1,type:0 },{ name:2,type:0 }]
 *  ...
 * }
 *
 *   ]
 */

const arrTest = [
	{
		name: 1,
		type: 0,
	},
	{
		name: 2,
		type: 0,
	},
	{
		name: 3,
		type: 2,
	},
	{
		name: 4,
		type: 2,
	},
	{
		name: 5,
		type: 3,
	},
	{
		name: 6,
		type: 3,
	},
]

// let result = []
// let final = []
// arrTest.forEach((item) => !result.includes(item.type) && result.push(item.type))

// result.forEach((item, index) => (result[index] = { type: item, values: [] }))

// arrTest.forEach((item) => {
// 	const index = result.find((i) => i.type == item.type)
// 	if (index) {
// 		index.values.push(item)
// 		final.push(index)
// 	}
// })

// function uniqueFunc(arr, uniId) {
// 	const res = new Map()
// 	return arr.filter((item) => !res.has(item[uniId]) && res.set(item[uniId], 1))
// }

// result.forEach((item) => (result = unique(final, item)))
// console.log(result)

/***
 * 按照 arr2 的顺序排列 arr1  arr2 中没有就按arr1的顺序排列
 */
// function foo() {
// 	let arr = [2, 3, 1, 3, 2, 4, 6, 7, 9, 2, 19]
// 	let arr2 = [2, 1, 4, 3, 9, 6]
// 	let result = []
// 	for (let i = 0; i < arr2.length; i++) {
// 		let index = -33
// 		while (index !== -1) {
// 			index = arr.findIndex((item) => item === arr2[i])
// 			if (index !== -1) {
// 				result.push(arr2[i])
// 				arr.splice(index, 1)
// 			}
// 		}
// 	}
// 	result = [...result, ...arr]
// 	console.log(result)
// }
// foo()

/**
 * 统计字符串 空格 数字 其他字符
 */

// function foo1(str = 'xxxxfajkgj   ** 1544545') {
// 	let d = 0
// 	let num = 0
// 	let space = 0
// 	let other = 0
// 	for (let i = 0; i < str.length; i++) {
// 		if (/\s/.test(str[i])) {
// 			space++
// 		} else if (/\d/.test(str[i])) {
// 			num++
// 		} else if (/[a-zA-Z]/.test(str[i])) {
// 			d++
// 		} else {
// 			other++
// 		}
// 	}
// 	console.log(d, num, space, other)
// }
// foo1()

/**
 * 击鼓传花 缝3退出
 */

// function foo() {
// 	let arr = ['张三', '李四', '王五', '赵六']
// 	let i = 0
// 	while (arr.length > 1) {
// 		i++
// 		if (i % 3 == 0) {
// 			arr.shift()
// 			i = 0
// 		} else {
// 			arr.push(arr.shift())
// 		}
// 	}
// 	console.log(arr)
// }
// foo()

let person = function () {}
let no = new person()
// console.log(no instance_of2 person)
/**
 *  instanceOf 实现
 * @param {*} left
 * @param {*} right
 * @returns
 */

// function instance_of(left, right) {
// 	let rightVal = right.prototype
// 	left = left.__proto__
// 	while (true) {
// 		if (left == null) {
// 			return false
// 		}
// 		if (left === rightVal) {
// 			return true
// 		}
// 		left = left.__proto__
// 	}
// }

function instance_of22(A, B) {
	let left = A
	while (!!left) {
		const temp = Reflect.getPrototypeOf(left)
		console.log(Reflect.getPrototypeOf(left) === left.__proto__)
		if (temp === B.prototype) {
			return true
		}
		left = temp
	}
	return false
}

function Parent() {}
function Sone() {}
Sone.prototype = new Parent()
let s = new Sone()
console.log(instance_of22(s, Parent))

/**
 * 迭代器生成器
 * @param {*} x
 * @returns
 */
// function* foo(x) {
// 	let y = 2 * (yield x + 1)
// 	let z = yield y / 3
// 	console.log(x, y, z)
// 	return y + z + x
// }
// let it = foo(5)
// console.log(it.next().value) // => {value: 6, done: false}
// console.log(it.next(6).value) // => {value: 4, done: false}
// console.log(it.next(4).value) // => {value: 21, done: true}

/**
 * 实现一个 Scheduler 类，完成对Promise的并发处理，最多同时执行2个任务
 */
// class Scheduler {
// 	static maxCount = 2
// 	constructor(max) {
// 		Scheduler.maxCount = max
// 		this.task = []
// 		this.count = 0
// 	}
// 	add(promiseCreator) {
// 		if (this.count < Scheduler.maxCount) {
// 			this.start(promiseCreator)
// 		} else {
// 			this.task.push(promiseCreator)
// 		}
// 	}
// 	async start(promiseCreator) {
// 		this.count += 1
// 		await promiseCreator()
// 		this.count -= 1
// 		if (this.task.length) {
// 			this.start(this.task.shift())
// 		}
// 	}
// }
// const scheduler = new Scheduler(2)
// const timeout = (time) =>
// 	new Promise((resolve) => {
// 		setTimeout(resolve, time)
// 	})
// const addTask = (time, order) => {
// 	scheduler.add(() => timeout(time).then(() => console.log(order)))
// }

// addTask(1000, 1)
// addTask(500, 2)
// addTask(300, 3)
// addTask(400, 4)

let ob = {
	address: 45,
}
let o = Object.create(ob)
o.name = 4
o.age = 4

// console.log(Reflect.ownKeys(o))
// console.log(Object.keys(o))
// console.log(o.address)
// console.dir(o)

/**
 * ES5 ES6 继承的差异
 */

// function ArrFun() {
// 	Array.call(this)
// }

// ArrFun.prototype = Object.create(Array.prototype, {
// 	constructor: {
// 		value: ArrFun,
// 		writable: true,
// 		configurable: true,
// 	},
// })

// var colors = new ArrFun()
// colors[0] = 'blue'

// class ArrFun extends Array {
// 	constructor() {
// 		super()
// 	}
// }

// var colors = new ArrFun()
// colors[0] = 12
// console.log(colors.length)
// console.dir(colors)

/**
 * 深拷贝 函数
 */
// function foo() {}

// let object3 = {
// 	name: {
// 		arr: [1, 2, 3],
// 		address: {
// 			arr2: [3, 1, 5],
// 		},
// 	},
// }

// function deepCopy(data, hash = new WeakMap()) {
// 	if (typeof data !== 'object' || data === null) {
// 		throw new TypeError('传入参数不是对象')
// 	}
// 	// 判断传入的待拷贝对象的引用是否存在于hash中
// 	if (hash.has(data)) {
// 		return hash.get(data)
// 	}
// 	let newData = {}
// 	const dataKeys = Object.keys(data)
// 	dataKeys.forEach((value) => {
// 		const currentDataValue = data[value]
// 		// 基本数据类型的值和函数直接赋值拷贝
// 		if (typeof currentDataValue !== 'object' || currentDataValue === null) {
// 			newData[value] = currentDataValue
// 		} else if (Array.isArray(currentDataValue)) {
// 			// 实现数组的深拷贝
// 			newData[value] = [...currentDataValue]
// 		} else if (currentDataValue instanceof Set) {
// 			// 实现set数据的深拷贝
// 			newData[value] = new Set([...currentDataValue])
// 		} else if (currentDataValue instanceof Map) {
// 			// 实现map数据的深拷贝
// 			newData[value] = new Map([...currentDataValue])
// 		} else {
// 			// 将这个待拷贝对象的引用存于hash中
// 			hash.set(data, data)
// 			// 普通对象则递归赋值
// 			newData[value] = deepCopy(currentDataValue, hash)
// 		}
// 	})
// 	return newData
// }

// let ooo = deepCopy(object3)
// console.log(ooo)
// object3.name.address = 1000
// console.log(object3)

/**
 * 获取URL参数
 *https://www.nowcoder.com/issue/tutorial?tutorialId=96&uuid=614ed46bbd9c483597ef89b8abfc9084
 */
// function getUrlParams(
// 	str = 'https://www.nowcoder.com/issue/tutorial?tutorialId=96&uuid=614ed46bbd9c483597ef89b8abfc9084'
// ) {
// 	let params = {}
// 	str
// 		.split('?')[1]
// 		.split('&')
// 		.forEach((item) => {
// 			const key = item.split('=')[0]
// 			const val = item.split('=')[1]
// 			params[key] = val
// 		})
// 	console.log(params)
// }
// getUrlParams()

// function createdParams(obj = { name: 'lisi', age: 45 }) {
// 	let paramsStr = ''
// 	for (const key in obj) {
// 		if (Object.hasOwnProperty.call(obj, key)) {
// 			const val = obj[key]
// 			paramsStr += `${key}=${val}&`
// 		}
// 	}
// 	paramsStr = '?' + paramsStr.slice(0, -1)
// 	console.log(paramsStr)
// }
// createdParams()

/**
 * 数字千分位截取
 */
// console.log((123464456789).toString().replace(/(\d)(?=(?:\d{3})+$)/g, '$1,'))
/**
 *  统计无重复的字符串最长子序列
 * @param {*} str
 */

// function lengthOfLongestSubstring(str = 'faelkfujgmfesffffs') {
// 	let temp = []
// 	let max = 0
// 	let result = ''
// 	for (let i = 0; i < str.length; i++) {
// 		temp = []
// 		for (let j = i + 1; j < str.length; j++) {
// 			const e = str[j]
// 			if (temp.includes(e)) {
// 				temp = []
// 				break
// 			} else {
// 				temp.push(str[j])
// 				temp.length > max
// 					? ((max = temp.length), (result = temp.join('')))
// 					: (max = max)
// 			}
// 		}
// 	}
// 	console.log(result)
// }
// lengthOfLongestSubstring()

/**
 * 
 * 给定一个包含 n 个整数的数组 nums，判断 nums 中是否存在三个元素 a，b，c ，使得 a + b + c = 0 ？找出所有满足条件且不重复的三元组。
 * 注意：答案中不可以包含重复的三元组。
 * 例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4]，
 * 满足要求的三元组集合为：
 * [
    [-1, 0, 1],
    [-1, -1, 2]
   ]
 * 
 */
// function threeSum(nums = [-1, 0, 1, 2, -1, -4]) {
// 	let result = []
// 	// 小于三个数
// 	if (nums).length < 3) return []
// 	// 排序 升序
// 	nums.sort((a, b) => a - b)
// 	//  前后两个数相等 就跳过
// 	for (let i = 0; i < nums.length; i++) {
// 		if (i > 0 && nums[i] == nums[i - 1]) {
// 			continue
// 		}
// 		//  第一个数 大于 0 直接结束
// 		if (nums[i] > 0) break
// 		// 二分查找
// 		let l = i + 1,
// 			r = nums.length - 1
// 		while (l < r) {
// 			let sum = nums[l] + nums[r] + nums[i]
// 			if (sum == 0) {
// 				result.push([nums[i], nums[l], nums[r]])
// 				while (l < r && nums[l] == nums[l + 1]) {
// 					l++
// 				}
// 				while (l < r && nums[r] == nums[r - 1]) {
// 					r--
// 				}
// 				l++
// 				r--
// 			} else if (sum < 0) {
// 				l++
// 			} else if (sum > 0) {
// 				r--
// 			}
// 		}
// 	}

// 	console.log(result)
// }
// threeSum()

// 寻找子集

// function foo(arr = [1, 2, 3]) {
// 	let res = [[]]
// 	for (let i = 0; i < arr.length; i++) {
// 		const tempRes = res.map((subset) => {
// 			const one = subset.concat([])
// 			one.push(arr[i])
// 			return one
// 		})
// 		res = res.concat(tempRes)
// 		console.log(res)
// 	}
// }
// foo()
